package com.kris;

import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
import java.text.ParseException;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;

/**
 * 界面主程序, 使用NetBeans的图形界面编辑程序绘制.
 *
 * @author zhangqunshi
 */
public class main extends javax.swing.JFrame {

    /**
     * Creates new form main
     */
    public main() {
        initComponents();
    }

    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        employeesLabel = new javax.swing.JLabel();
        employeesFilePathTextField = new javax.swing.JTextField();
        employeeBrowerButton = new javax.swing.JButton();
        attendRecordLabel = new javax.swing.JLabel();
        attendRecordFilePathTextField = new javax.swing.JTextField();
        attendRecordBrowerButton = new javax.swing.JButton();
        dateScopeLabel = new javax.swing.JLabel();
        beginDateTextField = new javax.swing.JTextField();
        endDateLabel = new javax.swing.JLabel();
        endDateTextField = new javax.swing.JTextField();
        holidayLabel = new javax.swing.JLabel();
        holidayTextField = new javax.swing.JTextField();
        beginDateLabel = new javax.swing.JLabel();
        okButton = new javax.swing.JButton();
        closeButton = new javax.swing.JButton();
        fileTypeDescriptionLabel = new javax.swing.JLabel();
        holidayNoteLabel = new javax.swing.JLabel();
        outputTextField = new javax.swing.JTextField();
        outputLabel = new javax.swing.JLabel();
        excludeHolidayLabel = new javax.swing.JLabel();
        excludeHolidayTextField = new javax.swing.JTextField();
        dateNoteLabel = new javax.swing.JLabel();
        mealTextField = new javax.swing.JTextField();
        mealLabel = new javax.swing.JLabel();
        yuanLabel = new javax.swing.JLabel();
        beginTimeLabel = new javax.swing.JLabel();
        companyBeginTimeTextField = new javax.swing.JTextField();
        mealTimeLabel = new javax.swing.JLabel();
        workOverTimeTextField = new javax.swing.JTextField();
        hourLabel = new javax.swing.JLabel();
        jLabel1 = new javax.swing.JLabel();
        companyEndTimeTextField = new javax.swing.JTextField();
        jLabel2 = new javax.swing.JLabel();
        lateTextField = new javax.swing.JTextField();
        jLabel3 = new javax.swing.JLabel();
        outputButton = new javax.swing.JButton();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setTitle("考勤工具v0.1");

        employeesLabel.setText("员工名单文件");

        employeeBrowerButton.setText("浏览");
        employeeBrowerButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                employeeBrowerButtonActionPerformed(evt);
            }
        });

        attendRecordLabel.setText("考勤记录文件");

        attendRecordBrowerButton.setText("浏览");
        attendRecordBrowerButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                attendRecordBrowerButtonActionPerformed(evt);
            }
        });

        dateScopeLabel.setText("指定时间范围:");

        endDateLabel.setText("结束时间");

        holidayLabel.setText("法定节假日：");

        beginDateLabel.setText(" 开始时间");

        okButton.setText("生成统计报表文件");
        okButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                okButtonActionPerformed(evt);
            }
        });

        closeButton.setText("关闭");
        closeButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                closeButtonActionPerformed(evt);
            }
        });

        fileTypeDescriptionLabel.setText("注: 员工文件和考勤记录文件都是excel文件, 员工名单文件只有一列员工姓名; 考勤为2列内容(姓名，时间)");

        holidayNoteLabel.setText("注意: 节假日连续日期可以使用~来指定范围,使用逗号分隔. 例如: 20161001~20161007, 20161012");

        outputLabel.setText("输出路径：");

        excludeHolidayLabel.setText("排除节假日：");

        dateNoteLabel.setText("日期格式为：yyyy-MM-dd, 例如：2016-11-9");

        mealTextField.setText("20");

        mealLabel.setText("餐补每天金额");

        yuanLabel.setText("元");

        beginTimeLabel.setText("公司上班时间:");

        companyBeginTimeTextField.setText("9:00");

        mealTimeLabel.setText("餐补加班时长为");

        workOverTimeTextField.setText("1.5");

        hourLabel.setText("小时");

        jLabel1.setText("公司下班时间:");

        companyEndTimeTextField.setText("18:00");

        jLabel2.setText("迟到时长");

        lateTextField.setText("30");

        jLabel3.setText("分钟");

        outputButton.setText("浏览");
        outputButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                outputButtonActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(layout.createSequentialGroup()
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(employeesLabel)
                            .addComponent(attendRecordLabel)
                            .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                                .addComponent(dateScopeLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                                .addComponent(holidayLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addGroup(layout.createSequentialGroup()
                                .addComponent(beginDateLabel)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                .addComponent(beginDateTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 168, javax.swing.GroupLayout.PREFERRED_SIZE))
                            .addGroup(layout.createSequentialGroup()
                                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                                    .addComponent(employeesFilePathTextField, javax.swing.GroupLayout.DEFAULT_SIZE, 427, Short.MAX_VALUE)
                                    .addComponent(attendRecordFilePathTextField))
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                    .addComponent(employeeBrowerButton, javax.swing.GroupLayout.Alignment.TRAILING)
                                    .addComponent(attendRecordBrowerButton, javax.swing.GroupLayout.Alignment.TRAILING)))
                            .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
                                .addComponent(excludeHolidayTextField, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 484, Short.MAX_VALUE)
                                .addComponent(holidayTextField, javax.swing.GroupLayout.Alignment.LEADING))
                            .addComponent(dateNoteLabel)))
                    .addComponent(excludeHolidayLabel)
                    .addComponent(holidayNoteLabel)
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(mealLabel)
                        .addGap(18, 18, 18)
                        .addComponent(mealTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 46, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(yuanLabel)
                        .addGap(38, 38, 38)
                        .addComponent(mealTimeLabel)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                        .addComponent(workOverTimeTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 45, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(hourLabel))
                    .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                        .addGroup(layout.createSequentialGroup()
                            .addComponent(endDateLabel)
                            .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                            .addComponent(endDateTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 174, javax.swing.GroupLayout.PREFERRED_SIZE)
                            .addGap(8, 8, 8))
                        .addComponent(fileTypeDescriptionLabel)
                        .addGroup(layout.createSequentialGroup()
                            .addComponent(okButton, javax.swing.GroupLayout.PREFERRED_SIZE, 214, javax.swing.GroupLayout.PREFERRED_SIZE)
                            .addGap(18, 18, 18)
                            .addComponent(closeButton, javax.swing.GroupLayout.PREFERRED_SIZE, 135, javax.swing.GroupLayout.PREFERRED_SIZE)))
                    .addGroup(layout.createSequentialGroup()
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
                            .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup()
                                .addComponent(outputLabel)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                .addComponent(outputTextField))
                            .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup()
                                .addComponent(beginTimeLabel)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                                .addComponent(companyBeginTimeTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 48, javax.swing.GroupLayout.PREFERRED_SIZE)
                                .addGap(54, 54, 54)
                                .addComponent(jLabel1)
                                .addGap(18, 18, 18)
                                .addComponent(companyEndTimeTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 52, javax.swing.GroupLayout.PREFERRED_SIZE)
                                .addGap(29, 29, 29)
                                .addComponent(jLabel2)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                                .addComponent(lateTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 49, javax.swing.GroupLayout.PREFERRED_SIZE)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                                .addComponent(jLabel3)))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(outputButton)))
                .addContainerGap(11, Short.MAX_VALUE))
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(employeesLabel)
                    .addComponent(employeesFilePathTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(employeeBrowerButton))
                .addGap(18, 18, 18)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(attendRecordLabel)
                    .addComponent(attendRecordFilePathTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(attendRecordBrowerButton))
                .addGap(18, 18, 18)
                .addComponent(fileTypeDescriptionLabel)
                .addGap(35, 35, 35)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(dateScopeLabel)
                    .addComponent(beginDateTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(endDateLabel)
                    .addComponent(endDateTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(beginDateLabel))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(dateNoteLabel)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(holidayLabel)
                    .addComponent(holidayTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(excludeHolidayLabel)
                    .addComponent(excludeHolidayTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addGap(18, 18, 18)
                .addComponent(holidayNoteLabel)
                .addGap(18, 18, 18)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(mealTextField)
                    .addComponent(mealLabel)
                    .addComponent(yuanLabel)
                    .addComponent(mealTimeLabel)
                    .addComponent(workOverTimeTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(hourLabel))
                .addGap(18, 18, 18)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(beginTimeLabel)
                    .addComponent(companyBeginTimeTextField)
                    .addComponent(jLabel1)
                    .addComponent(companyEndTimeTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jLabel2)
                    .addComponent(lateTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jLabel3))
                .addGap(17, 17, 17)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(outputLabel)
                    .addComponent(outputTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(outputButton))
                .addGap(18, 18, 18)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(okButton, javax.swing.GroupLayout.PREFERRED_SIZE, 41, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(closeButton, javax.swing.GroupLayout.PREFERRED_SIZE, 41, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addContainerGap())
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void okButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_okButtonActionPerformed
        // 读取员工名单
        String employeeFile = this.employeesFilePathTextField.getText();

        List<String> employeeList = null;
        try {
            // 员工数据在第一个工作簿的第三列上
            employeeList = ExcelUtils.readColumn(employeeFile, 0, 2);
        } catch (IOException ex) {
            JOptionPane.showMessageDialog(this,
                    "读取员工名单文件错误:" + ex.getMessage(),
                    "文件错误",
                    JOptionPane.ERROR_MESSAGE);
            return;
        } catch (InvalidFormatException ex) {
            JOptionPane.showMessageDialog(this,
                    "员工名单文件格式错误:" + ex.getMessage(),
                    "格式错误",
                    JOptionPane.ERROR_MESSAGE);
            return;
        }

        // 过滤考勤时间
        String datePattern = "yyyy-MM-dd";
        Date beginDate;
        Date endDate;
        try {
            beginDate = DateUtil.parse(this.beginDateTextField.getText(), datePattern);
            endDate = DateUtil.parse(this.endDateTextField.getText(), datePattern);
        } catch (ParseException ex) {
            JOptionPane.showMessageDialog(this,
                    "日期输入错误:" + ex,
                    "日期错误",
                    JOptionPane.ERROR_MESSAGE);
            Logger.getLogger(main.class.getName()).log(Level.SEVERE, null, ex);
            return;
        }

        // 餐补金额
        String moneyPerDay = this.mealTextField.getText();
        if (moneyPerDay == null || "".equals(moneyPerDay.trim())) {
            JOptionPane.showMessageDialog(this, "请输入餐补每天金额");
            return;
        }

        // 公司的上班时间 (餐补报表使用此值)
        String companyBeginTime = this.companyBeginTimeTextField.getText();
        if (companyBeginTime == null || "".equals(companyBeginTime.trim())) {
            JOptionPane.showMessageDialog(this, "请输入公司开始上班时间");
            return;
        }
        // 公司的下班时间
        String companyEndTime = this.companyEndTimeTextField.getText();
        if (companyEndTime == null || "".equals(companyEndTime.trim())) {
            JOptionPane.showMessageDialog(this, "请输入公司下班时间");
            return;
        }

        // 迟到时长
        String lateTime = this.lateTextField.getText();
        if (lateTime == null || "".equals(lateTime.trim())) {
            JOptionPane.showMessageDialog(this, "请输入迟到时长");
            return;
        }

        int lateWorkTime = 0;
        try {
            lateWorkTime = Integer.parseInt(lateTime);
        } catch (Exception e) {
            JOptionPane.showMessageDialog(this, "迟到时长格式错误，应为小数");
            return;
        }

        // 餐补加班时长
        String overTime = this.workOverTimeTextField.getText();
        if (overTime == null || "".equals(overTime.trim())) {
            JOptionPane.showMessageDialog(this, "请输入餐补加班时长");
            return;
        }
        double workOverTimeForMeal = Double.valueOf(overTime.trim());

        // 读取员工打卡信息(要求在第一个sheet中)
        String attendRecordFile = this.attendRecordFilePathTextField.getText();
        List<ExcelRow> rows;
        try {
            DateFilter dateFilter = null;
            if (beginDate != null || endDate != null) {
                // 考勤的日期列在第3列，所以列的索引是2
                dateFilter = new DateFilter(beginDate, endDate, 2);
            }
            // sheet is 0, 从第2行开始读取
            rows = ExcelUtils.readLines(attendRecordFile, 0, 2, dateFilter);
        } catch (IOException ex) {
            JOptionPane.showMessageDialog(this,
                    "读取考勤文件错误:" + ex,
                    "文件错误",
                    JOptionPane.ERROR_MESSAGE);
            Logger.getLogger(main.class.getName()).log(Level.SEVERE, null, ex);
            return;
        } catch (InvalidFormatException ex) {
            JOptionPane.showMessageDialog(this,
                    "考勤文件格式错误:" + ex.getMessage(),
                    "格式错误",
                    JOptionPane.ERROR_MESSAGE);
            return;
        } catch (Exception ex) {
            JOptionPane.showMessageDialog(this,
                    "考勤文件日期过滤错误:" + ex.getMessage(),
                    "格式错误",
                    JOptionPane.ERROR_MESSAGE);
            Logger.getLogger(main.class.getName()).log(Level.SEVERE, null, ex);
            return;
        }

        Map<String, EmployeeAttendRecord> records;
        try {
            records = EmployeeAttendRecord.valueFrom(rows);
        } catch (ParseException ex) {
            JOptionPane.showMessageDialog(this,
                    "解析报表错误:" + ex,
                    "解析报表错误",
                    JOptionPane.ERROR_MESSAGE);
            return;
        }

        // 设置报表文件的输出路径
        String outputPath = this.outputTextField.getText();
        if (outputPath == null || "".equals(outputPath.trim())) {
            JOptionPane.showMessageDialog(this,
                    "请指定输出路径",
                    "错误",
                    JOptionPane.ERROR_MESSAGE);
            return;
        }

        // 计算节假日
        String holidayStr = this.holidayTextField.getText();
        String excludeHolidayStr = this.excludeHolidayTextField.getText();
        List<Date> holidays;
        List<Date> excludeHolidays;
        try {
            holidays = DateUtil.parseHoliday(holidayStr);
            excludeHolidays = DateUtil.parseHoliday(excludeHolidayStr);
        } catch (ParseException ex) {
            JOptionPane.showMessageDialog(this,
                    "法定节假日设置错误:" + ex.getMessage(),
                    "法定节假日错误",
                    JOptionPane.ERROR_MESSAGE);
            Logger.getLogger(main.class.getName()).log(Level.SEVERE, null, ex);
            return;
        }

        // 生成节假日加班报表
        String filePath = outputPath + File.separator + "节假日加班统计表.xls";
        System.out.println(filePath);
        Report overtimeReport = new WeekendHolidayOverTimeReport(filePath,
                employeeList, records, holidays, excludeHolidays);
        try {
            overtimeReport.make();
        } catch (Exception ex) {
            JOptionPane.showMessageDialog(this,
                    "生成节假日加班报表错误:" + ex.getMessage(),
                    "生成节假日加班报表错误",
                    JOptionPane.ERROR_MESSAGE);
            Logger.getLogger(main.class.getName()).log(Level.SEVERE, null, ex);
            return;
        }

        // 餐补报表
        Report mealReport = new MealReport(
                outputPath + File.separator + "加班餐补统计表.xls",
                employeeList,
                records,
                holidays,
                excludeHolidays,
                new BigDecimal(moneyPerDay.trim()),
                companyBeginTime,
                workOverTimeForMeal);
        try {
            mealReport.make();
        } catch (Exception ex) {
            JOptionPane.showMessageDialog(this,
                    "生成加班餐补表错误:" + ex.getMessage(),
                    "生成加班餐补表错误",
                    JOptionPane.ERROR_MESSAGE);
            Logger.getLogger(main.class.getName()).log(Level.SEVERE, null, ex);
            return;
        }

        // 出勤报表
        Report workOverTimeReport = new WorkOverTimeReport(
                outputPath + File.separator + "加班时长统计.xls",
                employeeList,
                records,
                holidays,
                excludeHolidays);
        try {
            workOverTimeReport.make();
        } catch (Exception ex) {
            JOptionPane.showMessageDialog(this,
                    "生成加班时长表错误:" + ex.getMessage(),
                    "生成加班时长表错误",
                    JOptionPane.ERROR_MESSAGE);
            Logger.getLogger(main.class.getName()).log(Level.SEVERE, null, ex);
            return;
        }

        // 倒休时长统计报表
        Report compReport = new TimeCompensationReport(
                outputPath + File.separator + "倒休时长统计.xls",
                employeeList,
                records,
                holidays,
                excludeHolidays,
                companyBeginTime,
                companyEndTime,
                lateWorkTime
        );
        try {
            compReport.make();
        } catch (Exception ex) {
            JOptionPane.showMessageDialog(this,
                    "生成倒休时长统计表错误:" + ex.getMessage(),
                    "生成倒休时长统计表错误",
                    JOptionPane.ERROR_MESSAGE);
            Logger.getLogger(main.class.getName()).log(Level.SEVERE, null, ex);
            return;
        }

        JOptionPane.showMessageDialog(this, "生成报表成功");

    }//GEN-LAST:event_okButtonActionPerformed

    private void closeButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_closeButtonActionPerformed
        // 关闭程序
        this.dispose();
    }//GEN-LAST:event_closeButtonActionPerformed

    private void employeeBrowerButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_employeeBrowerButtonActionPerformed
        // 打开文件选择对话框,让用户选择员工名单Excel文件,文件内部只有一列数据(必须为第一列),
        // 即为员工姓名, 每个员工一行, 员工姓名不能重复.
        JFileChooser jfc;
        if (latestPath != null) {
            jfc = new JFileChooser(latestPath);
        } else {
            jfc = new JFileChooser();
        }

        jfc.setFileSelectionMode(JFileChooser.FILES_ONLY);
        int returnVal = jfc.showOpenDialog(this);
        if (returnVal == JFileChooser.APPROVE_OPTION) {
            File file = jfc.getSelectedFile();
            latestPath = file.getParent();
            this.employeesFilePathTextField.setText(file.getAbsolutePath());
        }
    }//GEN-LAST:event_employeeBrowerButtonActionPerformed

    private void attendRecordBrowerButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_attendRecordBrowerButtonActionPerformed
        // 打开考勤记录Excel文档
        JFileChooser jfc;
        if (latestPath != null) {
            jfc = new JFileChooser(latestPath);
        } else {
            jfc = new JFileChooser();
        }
        jfc.setFileSelectionMode(JFileChooser.FILES_ONLY);
        int returnVal = jfc.showOpenDialog(this);
        if (returnVal == JFileChooser.APPROVE_OPTION) {
            File file = jfc.getSelectedFile();
            latestPath = file.getParent();
            this.attendRecordFilePathTextField.setText(file.getAbsolutePath());
        }
    }//GEN-LAST:event_attendRecordBrowerButtonActionPerformed

    private void outputButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_outputButtonActionPerformed
        JFileChooser jfc;
        if (latestPath != null) {
            jfc = new JFileChooser(latestPath);
        } else {
            jfc = new JFileChooser();
        }
        jfc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
        int returnVal = jfc.showOpenDialog(this);
        if (returnVal == JFileChooser.APPROVE_OPTION) {
            File file = jfc.getSelectedFile();
//            latestPath = file.getParent();
            this.outputTextField.setText(file.getAbsolutePath());
        }
    }//GEN-LAST:event_outputButtonActionPerformed

    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        /* Set the Nimbus look and feel */
        //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
        /* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
         * For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html 
         */
        try {
            for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) {
                    javax.swing.UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (ClassNotFoundException ex) {
            java.util.logging.Logger.getLogger(main.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (InstantiationException ex) {
            java.util.logging.Logger.getLogger(main.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            java.util.logging.Logger.getLogger(main.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (javax.swing.UnsupportedLookAndFeelException ex) {
            java.util.logging.Logger.getLogger(main.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }
        //</editor-fold>

        /* Create and display the form */
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                new main().setVisible(true);
            }
        });
    }

    private String latestPath;
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton attendRecordBrowerButton;
    private javax.swing.JTextField attendRecordFilePathTextField;
    private javax.swing.JLabel attendRecordLabel;
    private javax.swing.JLabel beginDateLabel;
    private javax.swing.JTextField beginDateTextField;
    private javax.swing.JLabel beginTimeLabel;
    private javax.swing.JButton closeButton;
    private javax.swing.JTextField companyBeginTimeTextField;
    private javax.swing.JTextField companyEndTimeTextField;
    private javax.swing.JLabel dateNoteLabel;
    private javax.swing.JLabel dateScopeLabel;
    private javax.swing.JButton employeeBrowerButton;
    private javax.swing.JTextField employeesFilePathTextField;
    private javax.swing.JLabel employeesLabel;
    private javax.swing.JLabel endDateLabel;
    private javax.swing.JTextField endDateTextField;
    private javax.swing.JLabel excludeHolidayLabel;
    private javax.swing.JTextField excludeHolidayTextField;
    private javax.swing.JLabel fileTypeDescriptionLabel;
    private javax.swing.JLabel holidayLabel;
    private javax.swing.JLabel holidayNoteLabel;
    private javax.swing.JTextField holidayTextField;
    private javax.swing.JLabel hourLabel;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JLabel jLabel3;
    private javax.swing.JTextField lateTextField;
    private javax.swing.JLabel mealLabel;
    private javax.swing.JTextField mealTextField;
    private javax.swing.JLabel mealTimeLabel;
    private javax.swing.JButton okButton;
    private javax.swing.JButton outputButton;
    private javax.swing.JLabel outputLabel;
    private javax.swing.JTextField outputTextField;
    private javax.swing.JTextField workOverTimeTextField;
    private javax.swing.JLabel yuanLabel;
    // End of variables declaration//GEN-END:variables
}
